package exredis

import (
	"github.com/gomodule/redigo/redis"
)

// 删除给定的一个或多个 key 。
// 不存在的 key 会被忽略。
// 返回值：
// 被删除 key 的数量。
func (r *Redis) DEL(keys ...interface{}) (int, error) {
	return redis.Int(r.PreDo("DEL", keys...))
}

// 序列化给定 key ，并返回被序列化的值，使用 RESTORE 命令可以将这个值反序列化为 Redis 键。
func (r *Redis) DUMP(key string) (string, error) {
	return redis.String(r.PreDo("DUMP", key))
}

// 检查给定 key 是否存在。
func (r *Redis) EXISTS(key string) (bool, error) {
	return redis.Bool(r.PreDo("EXISTS", key))
}

// 为给定 key 设置生存时间，当 key 过期时(生存时间为 0 )，它会被自动删除。
func (r *Redis) EXPIRE(key string, seconds int) (bool, error) {
	return redis.Bool(r.PreDo("EXPIRE", key, seconds))
}

// EXPIREAT 的作用和 EXPIRE 类似，都用于为 key 设置生存时间。
// 不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。
func (r *Redis) EXPIREAT(key string, unixTimestamp int64) (bool, error) {
	return redis.Bool(r.PreDo("EXPIREAT", key, unixTimestamp))
}

// 查找所有符合给定模式 pattern 的 key 。
// KEYS * 匹配数据库中所有 key 。
// KEYS h?llo 匹配 hello ， hallo 和 hxllo 等。
// KEYS h*llo 匹配 hllo 和 heeeeello 等。
// KEYS h[ae]llo 匹配 hello 和 hallo ，但不匹配 hillo 。
// 特殊符号用 \ 隔开
func (r *Redis) KEYS(pattern string) ([]string, error) {
	return redis.Strings(r.PreDo("KEYS", pattern))
}

// MIGRATE host port key destination-db timeout [COPY] [REPLACE]
// 将 key 原子性地从当前实例传送到目标实例的指定数据库上，一旦传送成功， key 保证会出现在目标实例上，而当前实例上的 key 会被删除。
func (r *Redis) MIGRATE(host, port, key, db string, timeoutMS int64) (bool, error) {
	return IsOK(redis.String(r.PreDo("MIGRATE", host, port, key, db, timeoutMS)))
}

// MOVE key db
// 将当前数据库的 key 移动到给定的数据库 db 当中。
// 如果当前数据库(源数据库)和给定数据库(目标数据库)有相同名字的给定 key ，或者 key 不存在于当前数据库，那么 MOVE 没有任何效果。
func (r *Redis) MOVE(key, db string) (bool, error) {
	return redis.Bool(r.PreDo("MOVE", key, db))
}

// OBJECT subcommand [arguments [arguments]]
// OBJECT 命令允许从内部察看给定 key 的 Redis 对象。

// OBJECT REFCOUNT <key> 返回给定 key 引用所储存的值的次数。此命令主要用于除错。
func (r *Redis) OBJECTREFCOUNT(key string) (int, error) {
	return redis.Int(r.PreDo("OBJECT", "REFCOUNT", key))
}

// OBJECT ENCODING <key> 返回给定 key 锁储存的值所使用的内部表示(representation)。
func (r *Redis) OBJECTENCODING(key string) (string, error) {
	return redis.String(r.PreDo("OBJECT", "ENCODING", key))
}

// OBJECT IDLETIME <key> 返回给定 key 自储存以来的空闲时间(idle， 没有被读取也没有被写入)，以秒为单位。
func (r *Redis) OBJECTIDLETIME(key string) (int64, error) {
	return redis.Int64(r.PreDo("OBJECT", "IDLETIME", key))
}

// PERSIST key
// 移除给定 key 的生存时间，将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。
func (r *Redis) PERSIST(key string) (bool, error) {
	return redis.Bool(r.PreDo("PERSIST", key))
}

// PEXPIRE key milliseconds
// 这个命令和 EXPIRE 命令的作用类似，但是它以毫秒为单位设置 key 的生存时间，而不像 EXPIRE 命令那样，以秒为单位。
func (r *Redis) PEXPIRE(key string, milliseconds int) (bool, error) {
	return redis.Bool(r.PreDo("PEXPIRE", key, milliseconds))
}

// PEXPIREAT key milliseconds-timestamp
// 这个命令和 EXPIREAT 命令类似，但它以毫秒为单位设置 key 的过期 unix 时间戳，而不是像 EXPIREAT 那样，以秒为单位。
func (r *Redis) PEXPIREAT(key string, unixTimestampMS int64) (bool, error) {
	return redis.Bool(r.PreDo("PEXPIREAT", key, unixTimestampMS))
}

// PTTL key
// 这个命令类似于 TTL 命令，但它以毫秒为单位返回 key 的剩余生存时间，而不是像 TTL 命令那样，以秒为单位。
func (r *Redis) PTTL(key string) (int64, error) {
	return redis.Int64(r.PreDo("PTTL", key))
}

// RANDOMKEY
// 从当前数据库中随机返回(不删除)一个 key 。
func (r *Redis) RANDOMKEY() ([]string, error) {
	return redis.Strings(r.PreDo("RANDOMKEY"))
}

// RENAME key newkey
// 将 key 改名为 newkey 。
// 当 key 和 newkey 相同，或者 key 不存在时，返回一个错误。
// 当 newkey 已经存在时， RENAME 命令将覆盖旧值。
func (r *Redis) RENAME(key, newkey string) (bool, error) {
	return IsOK(redis.String(r.PreDo("RENAME", key, newkey)))
}

// RENAMENX key newkey
// 当且仅当 newkey 不存在时，将 key 改名为 newkey 。
// 当 key 不存在时，返回一个错误。
func (r *Redis) RENAMENX(key, newkey string) (bool, error) {
	return redis.Bool(r.PreDo("RENAMENX", key, newkey))
}

// RESTORE key ttl serialized-value [REPLACE]
// 反序列化给定的序列化值，并将它和给定的 key 关联。
// 参数 ttl 以毫秒为单位为 key 设置生存时间；如果 ttl 为 0 ，那么不设置生存时间。
// RESTORE 在执行反序列化之前会先对序列化值的 RDB 版本和数据校验和进行检查，如果 RDB 版本不相同或者数据不完整的话，那么 RESTORE 会拒绝进行反序列化，并返回一个错误。
// 如果键 key 已经存在， 并且给定了 REPLACE 选项， 那么使用反序列化得出的值来代替键 key 原有的值； 相反地， 如果键 key 已经存在， 但是没有给定 REPLACE 选项， 那么命令返回一个错误。
func (r *Redis) RESTORE(key, ttl, value string, replace bool) (bool, error) {
	if replace {
		return IsOK(redis.String(r.PreDo("RESTORE", key, ttl, value, "REPLACE")))
	} else {
		return IsOK(redis.String(r.PreDo("RESTORE", key, ttl, value)))
	}
}

// SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC | DESC] [ALPHA] [STORE destination]
// 返回或保存给定列表、集合、有序集合 key 中经过排序的元素。
// 排序默认以数字作为对象，值被解释为双精度浮点数，然后进行比较。
func (r *Redis) SORT(args ...interface{}) ([]string, error) {
	return redis.Strings(r.PreDo("SORT", args...))
}

// 以秒为单位，返回给定 key 的剩余生存时间(TTL, time to live)。
// 当 key 不存在时，返回 -2 。
// 当 key 存在但没有设置剩余生存时间时，返回 -1 。
// 否则，以秒为单位，返回 key 的剩余生存时间。
func (r *Redis) TTL(key string) (int64, error) {
	return redis.Int64(r.PreDo("TTL", key))
}

// TYPE key
// 返回 key 所储存的值的类型。
func (r *Redis) TYPE(key string) (string, error) {
	return redis.String(r.PreDo("TYPE", key))
}

//TODO:SCAN cursor [MATCH pattern] [COUNT count]
func (r *Redis) SCAN() {
	//TODO:
}
